package com.google.code.sms.controller;

import com.google.code.sms.Logger;
import com.google.code.sms.domain.MediaElement;
import com.google.code.sms.domain.User;
import com.google.code.sms.service.MediaElementService;
import com.google.code.sms.service.MediaScannerService;
import com.google.code.sms.service.SecurityService;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.ParameterizableViewController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Controller for the home page.
 *
 * @author Sindre Mehus
 */
public class HomeController extends ParameterizableViewController {

    private static final Logger LOG = Logger.getLogger("HomeController");
    private static final int DEFAULT_LIST_SIZE = 10;
    private static final int MAX_LIST_SIZE = 500;
    private static final int DEFAULT_LIST_OFFSET = 0;
    private static final int MAX_LIST_OFFSET = 5000;
    private MediaScannerService mediaScannerService;
    private SecurityService securityService;
    private MediaElementService mediaElementService;

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {

        User user = securityService.getCurrentUser(request);
        int listSize = DEFAULT_LIST_SIZE;
        int listOffset = DEFAULT_LIST_OFFSET;
        if (request.getParameter("listSize") != null) {
            listSize = Math.max(0, Math.min(Integer.parseInt(request.getParameter("listSize")), MAX_LIST_SIZE));
        }
        if (request.getParameter("listOffset") != null) {
            listOffset = Math.max(0, Math.min(Integer.parseInt(request.getParameter("listOffset")), MAX_LIST_OFFSET));
        }

        String listType = request.getParameter("listType");
        if (listType == null) {
            listType = "newest";
        }

        List<MediaElement> elements;
        if ("frequent".equals(listType)) {
            elements = getMostFrequent(listOffset, listSize);
        } else if ("recent".equals(listType)) {
            elements = getMostRecent(listOffset, listSize);
        } else if ("newest".equals(listType)) {
            elements = getNewest(listOffset, listSize);
        } else if ("alphabetical".equals(listType)) {
            elements = getAlphabetical(listOffset, listSize);
        } else {
            elements = Collections.emptyList();
        }

        Map<String, Object> map = new HashMap<>();
        map.put("elements", elements);
        map.put("isIndexBeingCreated", mediaScannerService.isScanning());
        map.put("listType", listType);
        map.put("listSize", listSize);
        map.put("listOffset", listOffset);

        ModelAndView result = super.handleRequestInternal(request, response);
        result.addObject("model", map);
        return result;
    }

    List<MediaElement> getMostFrequent(int offset, int count) {
        List<MediaElement> result = new ArrayList<>();
        for (MediaElement mediaElement : mediaElementService.getMostFrequentlyPlayed(offset, count)) 
        {
            if (mediaElement != null)
            {
                result.add(mediaElement);
            }
        }
        return result;
    }

    List<MediaElement> getMostRecent(int offset, int count) {
        List<MediaElement> result = new ArrayList<>();
        for (MediaElement mediaElement : mediaElementService.getMostRecentlyPlayed(offset, count)) 
        {
            if (mediaElement != null)
            {
                result.add(mediaElement);
            }
        }
        return result;
    }

    List<MediaElement> getNewest(int offset, int count) throws IOException {
        List<MediaElement> result = new ArrayList<>();
        for (MediaElement mediaElement : mediaElementService.getMostRecentlyAdded(offset, count)) 
        {
            if (mediaElement != null)
            {
                result.add(mediaElement);
            }
        }
        return result;
    }

    List<MediaElement> getAlphabetical(int offset, int count) throws IOException {
        List<MediaElement> result = new ArrayList<>();
        for (MediaElement mediaElement : mediaElementService.getAlphabeticalDirectoryElements(offset, count)) 
        {
            if (mediaElement != null) {
                result.add(mediaElement);
            }
        }
        return result;
    }

    public void setMediaScannerService(MediaScannerService mediaScannerService) {
        this.mediaScannerService = mediaScannerService;
    }

    public void setSecurityService(SecurityService securityService) {
        this.securityService = securityService;
    }

    public void setMediaElementService(MediaElementService mediaElementService) {
        this.mediaElementService = mediaElementService;
    }
}
